#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht;

const char *ssid = "10U";
const char *password = "1234567890";
const char *mqttServer = "70227020fc.st1.iotda-device.cn-north-4.myhuaweicloud.com";
const int mqttPort = 1883;
const char *mqttClientId = "66125fab71d845632a043ad2_soil_0_0_2024040708";
const char *mqttUser = "66125fab71d845632a043ad2_soil";
const char *mqttPassword = "e414775f4bbeeb2ed3cba920d4d0c06f6e8f784a4e7e5bf9a8e9d57fec2b52a2";

#define deviceId "66125fab71d845632a043ad2_soil"

#define mqttTopic "$oc/devices/" deviceId "/sys/messages/down"

#define ALINK_BODY_FORMAT "{\"services\":[{\"service_id\":\"soilx\",\"properties\":%s}]}"
#define ALINK_TOPIC_PROP_POST "$oc/devices/{" deviceId "/sys/properties/report"

// 接收平台下发的命令
#define Iot_link_MQTT_Topic_Commands "$oc/devices/" deviceId "/sys/commands/#"
// 设备相应平台的命令
#define Iot_link_MQTT_Topic_CommandsRes "$oc/devices/" deviceId "/sys/commands/response/request_id="

WiFiClient espClient;
PubSubClient client(espClient);


#define soil_Pin 34 // 土壤湿度感应引脚(ADC)
int soil_value = 0; // 土壤湿度值

#define light_Pin 35 // 光线感应引脚（ADC）
int light_value = 0; // 光线值

#define water_Pin 32 // 水泵引脚（PWM）
bool water_flag = false;

#define fan_Pin 33 // 风扇引脚（PWM）
bool fan_flag = false;

#define LED_Pin 19 // 灯引脚
bool led_flag = false;

float tempx = 0;
float humix = 0;

int tempxs = 0;
int humixs = 0;

bool intelligent_flag = false; // 智能模式标记

int lastMsMain = 0;

sensors_event_t humidity, temp;

void setup()
{
    Serial.begin(115200);
    if (!aht.begin())
    {
        Serial.println("AHT10 error");
        while (1)
            delay(10);
    }
    Serial.println("AHT10已就绪！");
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(100);
        Serial.print(".");
    }
    Serial.println("wifi已连接");

    pinMode(soil_Pin, INPUT);
    pinMode(light_Pin, INPUT);

    pinMode(water_Pin, OUTPUT);
    pinMode(fan_Pin, OUTPUT);
    pinMode(LED_Pin, OUTPUT);

    digitalWrite(water_Pin, water_flag);
    digitalWrite(LED_Pin, !led_flag);
    digitalWrite(fan_Pin, fan_flag);

    // 初始化 iot，需传入 wifi 的 client，和设备产品信息
    client.setServer(mqttServer, mqttPort);
    client.setCallback(callback);
}

void loop()
{
    client.loop();
    if (!client.connected())
    {
        reconnect();
    }

    if (millis() - lastMsMain >= 2500) // 每2.5秒发送一次
    {

        lastMsMain = millis();
        aht.getEvent(&humidity, &temp);

        tempx = temp.temperature;
        humix = humidity.relative_humidity;

        tempxs = tempx * 100;
        humixs = humix * 100;

        // Serial.println(tempxs);
        // Serial.println(humixs);

        tempx = (float)tempxs / 100;
        humix = (float)humixs / 100;

        // Serial.println(tempx);
        // Serial.println(humix);

        soil_value = map(4095 - analogRead(soil_Pin), 0, 4095, 0, 100);
        light_value = 4095 - analogRead(light_Pin);
        // Serial.println(soil_value);
        // Serial.println(light_value);

        mqttIntervalPost();

        if (intelligent_flag)
        {
            intelligent_mode();
        }
    }
}
void intelligent_mode()
{
    if (soil_value < 25)
    {
        water_flag = true;
        digitalWrite(water_Pin, water_flag);
    }
    else
    {
        water_flag = false;
        digitalWrite(water_Pin, water_flag);
    }

    if (tempx > 32)
    {
        fan_flag = true;
        digitalWrite(fan_Pin, fan_flag);
    }
    else
    {
        fan_flag = false;
        digitalWrite(fan_Pin, fan_flag);
    }

    if (light_value < 2000)
    {
        led_flag = true;
        digitalWrite(LED_Pin, !led_flag);
    }
    else
    {
        led_flag = false;
        digitalWrite(LED_Pin, !led_flag);
    }
}

void mqttIntervalPost()
{
    char properties[64];
    char jsonBuf[512];

    sprintf(properties, "{\"soil_humi\":%d,\"light\":%d}", soil_value, light_value);
    sprintf(jsonBuf, ALINK_BODY_FORMAT, properties);
    boolean d = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
    Serial.println(jsonBuf);

    sprintf(properties, "{\"humidity\":%.2f,\"temp\":%.2f}", humix, tempx);
    sprintf(jsonBuf, ALINK_BODY_FORMAT, properties);
    d = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
    Serial.println(jsonBuf);
}

void reconnect()
{
    client.setServer(mqttServer, mqttPort);
    client.setCallback(callback);
    while (!client.connected())
    {
        Serial.println("Attempting MQTT connection...");
        if (client.connect(mqttClientId, mqttUser, mqttPassword))
        {
            Serial.println("connected");
            client.subscribe(mqttTopic);
        }
        else
        {
            Serial.print(client.state());
            delay(5000);
        }
    }
}

// void callback(char *topic, byte *payload, unsigned int length)
// {
//     StaticJsonDocument<128> doc;
//     DeserializationError error = deserializeJson(doc, payload);
//     if (error)
//     {
//         Serial.print(F("deserializeJson() failed: "));
//         Serial.println(error.c_str());
//         return;
//     }

//     const char *LEDKey = "LED";
//     const char *waterKey = "water";
//     const char *fanKey = "fan";
//     const char *intelligentKey = "intelligent";

//     if (doc.containsKey(LEDKey))
//     {
//         led_flag = doc[LEDKey];
//         digitalWrite(LED_Pin, !led_flag); // 控制
//         Serial.print("Switch LED: ");
//         Serial.println(led_flag ? "ON" : "OFF");
//     }

//     if (doc.containsKey(fanKey))
//     {
//         fan_flag = doc[fanKey];
//         digitalWrite(fan_Pin, fan_flag); // 控制
//         Serial.print("Switch fan: ");
//         Serial.println(fan_flag ? "ON" : "OFF");
//     }

//     if (doc.containsKey(waterKey))
//     {
//         water_flag = doc[waterKey];
//         digitalWrite(water_Pin, water_flag); // 控制
//         Serial.print("Switch water: ");
//         Serial.println(water_flag ? "ON" : "OFF");
//     }

//     if (doc.containsKey(intelligentKey))
//     {
//         intelligent_flag = doc[intelligentKey];
//         Serial.print("Switch intelligent: ");
//         Serial.println(intelligent_flag ? "ON" : "OFF");
//     }
// }

void callback(char *topic, byte *payload, unsigned int length)
{
    String recdata = "";
    Serial.printf("接收到订阅的消息:主题为：");
    Serial.println(topic);
    Serial.printf("数据内容：");
    for (int i = 0; i < length; i++)
    {
        recdata += (char)payload[i];
    }
    Serial.println(recdata);
    // 解析JSON数据
    DynamicJsonDocument jsonBuffer(1024);
    deserializeJson(jsonBuffer, recdata);
    JsonObject obj = jsonBuffer.as<JsonObject>();
    String com = obj["paras"];
    Serial.printf("解析命令:");
    Serial.println(com);
    deserializeJson(jsonBuffer, com);
    obj = jsonBuffer.as<JsonObject>();

    if ((int)obj["LED"] != 0)
        led_flag = (int)obj["LED"] - 1;
    if ((int)obj["fan"] != 0)
        fan_flag = (int)obj["fan"] - 1;
    if ((int)obj["water"] != 0)
        water_flag = (int)obj["water"] - 1;
    if ((int)obj["intelligent"] != 0)
        intelligent_flag = (int)obj["intelligent"] - 1;

    Serial.println("解析LED命令:");
    digitalWrite(LED_Pin, !led_flag); // 控制
    Serial.print("Switch LED: ");
    Serial.println(led_flag ? "ON" : "OFF");

    digitalWrite(fan_Pin, fan_flag); // 控制
    Serial.print("Switch fan: ");
    Serial.println(fan_flag ? "ON" : "OFF");

    digitalWrite(water_Pin, water_flag); // 控制
    Serial.print("Switch water: ");
    Serial.println(water_flag ? "ON" : "OFF");

    Serial.print("Switch intelligent: ");
    Serial.println(intelligent_flag ? "ON" : "OFF");

    // 解析request id，设备响应时的topic需要包含命令的request id，且会动态变化
    char *p = topic;
    String request_id = "";
    int i = 0;
    while ((*p++) != '\0') // 获取topic长度
    {
        i++;
    }
    topic += (i - 36);               // 移动指针位置
    for (int j = i - 36; j < i; j++) // 末36位为request id
        request_id += *topic++;
    Serial.println("request_id：" + request_id);
    Serial.println("命令设备响应");
    String param = "{}";
    client.publish((Iot_link_MQTT_Topic_CommandsRes + request_id).c_str(), param.c_str());
}